package org.korosoft.rusalad.syncnrun.cli;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.korosoft.rusalad.syncnrun.Main;
import org.korosoft.rusalad.syncnrun.Server;
import org.korosoft.rusalad.syncnrun.tools.InsecureSocketFactory;
import org.korosoft.rusalad.syncnrun.tools.KeyStore;
import org.korosoft.rusalad.syncnrun.tools.SecureSocketFactory;
import org.korosoft.rusalad.syncnrun.tools.SocketFactory;

import java.io.File;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Collection;

/**
 * CliServer command starts syncnrun server.
 *
 * @author Dmitry Korotkov
 * @since 1.0
 */
public class CliServer extends CliCommand {
    private static final Log log = LogFactory.getLog(CliServer.class);

    public CliServer() {
        super("server", "Starts syncnrun server");
        options.addOption("p", "port", true, String.format("Specify syncrun listening port (default is %d)", Main.DEFAULT_PORT));
        options.addOption(null, "insecure", false, "Start insecure server (without authentication/encryption)");
        options.addOption(null, "keystore", true, "Path to key store. Default is ~/.syncnrun");
        addCommonLoggingOpts();
    }

    @Override
    protected void doExecute(CommandLine commandLine) throws Exception {
        int port = Main.DEFAULT_PORT;
        final SocketFactory socketFactory;
        if (commandLine.hasOption("insecure")) {
            socketFactory = new InsecureSocketFactory();
        } else {
            final KeyStore keyStore;
            if (commandLine.hasOption("keystore")) {
                keyStore = new KeyStore(new File(commandLine.getOptionValue("keystore")));
            } else {
                keyStore = new KeyStore(new File(System.getProperty("user.home"), ".syncnrun"));
            }
            final PrivateKey privateKey = keyStore.getPrivateKey();
            final Collection<PublicKey> publicKeys = keyStore.getPublicKeys();
            if (publicKeys.size() == 0) {
                log.error(String.format("No client public keys found. Nobody will be able to connect."));
                System.exit(1);
            }
            socketFactory = new SecureSocketFactory(privateKey, publicKeys);
        }
        if (commandLine.hasOption("p")) {
            port = Integer.parseInt(commandLine.getOptionValue("p"));
        }
        Server server = new Server(socketFactory);
        server.start(port);
        log.info("Press ENTER to stop the server");
        System.in.read();
        server.stop();
        server.await();
    }
}
